using System;
using System.Net;
using System.Security;
using System.Xml;

namespace umlungu.engineX.webX {
	/// <summary>
	/// umlungu engineX web framework, error class.
	/// 	NB - errors defined in a xml resource file
	/// </summary>
	public class errorX
	{
		/// <summary>
		/// Local objects and properties
		/// </summary>
		private XmlDocument errxml;
		private string filename;
		public string FileName	{	get	{ return filename; }	set	{ filename = value;	} }
		
		private string property;
		public string Property	{
			get	{	return property;	}	
			set	{	property = value;	}
		}
		
		/// <summary>
		/// Public properties
		/// </summary>
		
		#region Public methods
		/// <summary>Constructor</summary>
		public errorX() {
			filename = "";
			errxml = new XmlDocument();
		}
		public errorX(string filestr) {
			filename = filestr;
			errxml = new XmlDocument();
			errxml.Load(filename);
		}
		/// <summary>
		/// Method description
		/// </summary>
		public void Load(string filestr) {
			filename = filestr;
			errxml.Load(filestr);
		}
		/// <summary>
		/// Method: Respond
		/// 	- Responds to the error by the appropriate action defined in the xml
		/// </summary>
		public void Respond(string errcde, sessionX sess) {
			if (errxml != null) {
				if (errxml.DocumentElement != null) {
					setError(errcde, sess);
				} else if (filename != "") {	// load the error file
					Load(filename);
					setError(errcde, sess);
				} else {
					sess.SetPage("errors", "system", "error", "general");
				}
			} else {	// Serve general error
				sess.SetPage("errors", "system", "error", "general");
			}
		}
		public void Respond(string errcde, contentX content) {
			if (errxml != null) {
				if (errxml.DocumentElement != null) {
					setError(errcde, content);
				} else if (filename != "") {	// load the error file
					Load(filename);
					setError(errcde, content);
				} else {
					content.SetPage("Error", "error_general", "errors", "system", "", "general");
				}
			} else {	// Serve general error
				content.SetPage("Error", "error_general", "errors", "system", "", "general");
			}
		}
		#endregion

		#region Protected methods
		#endregion

		#region Private methods
		/// <summary>
		/// Method: setError
		/// 	- Sets the error by the appropriate action defined in the xml
		/// </summary>
		private void setError(string errcde, sessionX sess) {
			XmlElement errsnode = (XmlElement) errxml.SelectSingleNode("//errors");
			XmlElement errnode = (XmlElement) errsnode.SelectSingleNode("error[@code='" + errcde + "']");
			if (errnode == null)
				errnode = (XmlElement) errsnode.SelectSingleNode("error[@code='" + errsnode.GetAttribute("default") + "']");
			// Now set the session based on error type
			if (errnode != null) {
				string errtype = errnode.GetAttribute("type");
				switch (errtype) {
					case "xml":
						sess.SetXml(errnode.GetAttribute("service"), errnode.GetAttribute("process"), errnode.InnerXml);
						break;
					case "page":
					default:
						sess.SetPage(errnode.GetAttribute("sect"), errnode.GetAttribute("sub"), errnode.GetAttribute("proc"), errnode.GetAttribute("page"));
						break;
				}
			} else
				sess.SetPage("errors", "system", "error", "general");
		}
		private void setError(string errcde, contentX content) {
			XmlElement errsnode = (XmlElement) errxml.SelectSingleNode("//errors");
			XmlElement errnode = (XmlElement) errsnode.SelectSingleNode("error[@code='" + errcde + "']");
			if (errnode == null)
				errnode = (XmlElement) errsnode.SelectSingleNode("error[@code='" + errsnode.GetAttribute("default") + "']");
			// Now set the session based on error type
			if (errnode != null) {
				string errtype = errnode.GetAttribute("type");
				switch (errtype) {
					case "xml":
						content.SetXml(errnode.OuterXml);
						break;
					case "page":
					default:
						content.SetPage(errnode.InnerText, "error_general", errnode.GetAttribute("sect"), errnode.GetAttribute("sub"), errnode.GetAttribute("proc"), errnode.GetAttribute("page"));
						break;
				}
			} else
				content.SetPage("Error", "error_general", "errors", "system", "", "general");
		}
		/// <summary>
		/// Method description
		/// </summary>
		private void throwError(string cde, string addmsg) {
			string errcde = cde, errmsg = ": error";
			if (errxml != null) {
				XmlElement errsnode = (XmlElement) errxml.SelectSingleNode("//errors");
				XmlElement errnode = (XmlElement) errxml.SelectSingleNode("//error[@code='" + errcde + "']");
				errmsg = String.Concat((errsnode != null)? errnode.GetAttribute("prefix") : "error", ": ", (errnode != null)? errnode.InnerText : "undescribed error");
			}
			if (addmsg != "")
				errmsg = String.Concat(errmsg, " - ", addmsg);
			throwErrorMsg(errcde, errmsg);
		}
		/// <summary>
		/// Method description
		/// </summary>
		private void throwErrorMsg(string errcde, string errmsg) {
			throw(new exceptionX(errcde, errmsg));
		}
		#endregion
	}
	
	
	public class exceptionX : Exception {
		private Exception except;
		private string code;
		public string Code	{
			get	{	return code;	}	
			set	{	code = value;	}
		}
		private string message;
		public override string Message	{
			get	{	return message;	}	
		}
		public XmlDocument Xml	{	// rather serialise the object to xml??
			get	{	
				XmlDocument thisdoc = new XmlDocument();
				string trace = (except !=null)? String.Concat(except.Message, " :: ", except.StackTrace) : "";
				thisdoc.LoadXml(String.Concat("<exceptionX><result><code>", code, "</code><message>", message, "</message></result><trace><![CDATA[", trace, "]]></trace></exceptionX>"));
				return(thisdoc);
			}	
		}
		
		#region Public methods
		/// <summary>Constructor</summary>
		/// <param name="code">Error code</param>
		/// <param name="message">Error message</param>
		public exceptionX(string cde, string msg) : base (msg) {
			code = cde;
			message = msg;
		}
		public exceptionX(string cde, params string[] msg) : base () {
			code = cde;
			message = String.Concat(msg);
		}
		public exceptionX(string cde, string msg, Exception exp) : base () {
			code = cde;
			message = String.Concat(msg);
			except = exp;
		}
		public exceptionX(string cde, string msg, SecurityException exp) : base () {
			code = cde;
			message = String.Concat(msg, " -- state:", exp.PermissionState, " -- set: <!--", exp.RefusedSet, "-->");
			except = exp;
		} 
		public exceptionX(string cde, string msg, WebException exp) : base () {
			code = cde;
			message = String.Concat(msg, " -- status:", exp.Status.ToString());
			except = exp;
		} 
		#endregion

	}
}
		
